﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Buccaneer.Properties;
using System.Drawing;
using System.IO;
using System.Threading;
using Buccaneer.Types;
using System.Diagnostics;
using PluginInterface;

namespace Buccaneer
{
    public enum SelectPosition { left, selected, right };

    #region TabButton

    public class TabEventArgs : MouseEventArgs
    {
        public int TabIndex;
        
        public TabEventArgs(MouseButtons mb, int clicks, int x, int y, int delta) : base(mb, clicks, x, y, delta) { }
        public TabEventArgs(EventArgs e) : base(((MouseEventArgs)e).Button, ((MouseEventArgs)e).Clicks, ((MouseEventArgs)e).X, ((MouseEventArgs)e).Y, ((MouseEventArgs)e).Delta) { }
    }

    public delegate void TabClickEventHandler(object sender, TabEventArgs e);

    public class TabButton : BitmapButton
    {
        public event TabClickEventHandler TabEvent = new TabClickEventHandler(tabswitchEvent);
        public TabHandler parent;
        protected override void OnClick(EventArgs e)
        {
            TabEventArgs te = new TabEventArgs(e);
            te.TabIndex = TabIndex;
            TabEvent(this, te);
            base.OnClick(e);
        }

        static void tabswitchEvent(object sender, TabEventArgs e)
        {
            ((TabButton)sender).parent.UpdateTabs(e.TabIndex);
        }
    }

    #endregion

    public class TabHandler : PluginServices
    {
        #region Public Attributes

        public Panel TabButtonContainer;
        public Panel TabContentContainer;
        public AvailablePlugin selectedPlugin;
        public Addressbar pathContainer;
        
        public Panel[] tabPages = null;
        public TabButton[] tabs = null;
        public TabButton selectedTab;
        public PictureBox[] tabSeparators = null;
        public static Bitmap tabSelected, tabUnselectedRight, tabUnselectedLeft, tabSeparatorLeft, tabSeparatorRight, tabEndRight;

        public static int selectedTabNo = -1;

        #endregion

        #region Initialize

        public TabHandler() : base()
        {
            try
            {
                tabSelected = new Bitmap(Directory.GetCurrentDirectory() + @"\Layout\tabSelected.png");
                tabUnselectedRight = new Bitmap(Directory.GetCurrentDirectory() + @"\Layout\tabUnselectedRight.png");
                tabUnselectedLeft = new Bitmap(Directory.GetCurrentDirectory() + @"\Layout\tabUnselectedLeft.png");
                tabSeparatorLeft = new Bitmap(Directory.GetCurrentDirectory() + @"\Layout\tabSeparatorLeft.png");
                tabSeparatorRight = new Bitmap(Directory.GetCurrentDirectory() + @"\Layout\tabSeparatorRight.png");
                tabEndRight = new Bitmap(Directory.GetCurrentDirectory() + @"\Layout\tabEndRight.png");
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Error in reading a tab layout image.\n\nException info: " + ex.Message);
                Console.ReadKey();
                Thread.CurrentThread.Abort();
                return;
            }
        }

        #endregion

        #region Add Functions

        public TabButton AddNewTab(string name, bool switchTo)
        {
            try
            {
                Array.Resize<TabButton>(ref tabs, tabs.Length + 1);
                Array.Resize<Panel>(ref tabPages, tabs.Length + 1);
            }
            catch (NullReferenceException)
            {
                tabs = new TabButton[] { new TabButton() };
                tabPages = new Panel[] { null };
            }

            tabs[tabs.Length - 1] = NewTab(name, SelectPosition.selected, tabs.Length - 1);
            tabPages[tabs.Length - 1] = new Panel();


            selectedPlugin = Global.Plugins.AvailablePlugins.Find(name);
            if (selectedPlugin != null)
            {
                selectedPlugin.Instance.Host = this;
                selectedPlugin.Instance.Navigating += new EventHandler(Instance_Navigating);

                if (switchTo)
                {
                    // Clear visuals: doesn't close the instance of the plugin
                    TabContentContainer.Controls.Clear();

                    // Set the dockstyle of the plugin to fill, to fill up the space provided
                    selectedPlugin.Instance.MainInterface.Dock = DockStyle.Fill;

                    // Finally, add the usercontrol to the panel
                    TabContentContainer.Controls.Add(selectedPlugin.Instance.MainInterface);
                }
            }

            return tabs[tabs.Length - 1];
        }

        static void Instance_Navigating(object sender, EventArgs e)
        {
            ((TabHandler)((IPlugin)sender).Host).pathContainer.Text = ((IPlugin)sender).Path;
        }

        private TabButton NewTab(string text, SelectPosition selected, int tabIndex)
        {
            TabButton newTab;

            Bitmap img = new Bitmap(Directory.GetCurrentDirectory() + @"\Layout\tabUnselected.png");

            newTab = new TabButton();
            newTab.Left =
                (((590 / tabs.Length) * tabIndex) < (tabSelected.Width - tabSeparatorLeft.Width) 
                    ? ((590 / tabs.Length) * tabIndex)
                    : (tabSelected.Width - tabSeparatorLeft.Width) * tabIndex);
            newTab.Top = 0;
            newTab.BackgroundImage = img;
            newTab.BackColor = Color.Transparent;
            newTab.Size = img.Size;
            newTab.TabIndex = tabIndex;
            newTab.Text = text;
        
            return newTab;
        }

        private PictureBox NewSeparator(int separatorNr, int selectedTab)
        {
            PictureBox imgPhoto = new PictureBox();
            imgPhoto.BorderStyle = BorderStyle.None;
            imgPhoto.Size = separatorNr == tabSeparators.Length - 1 ? tabEndRight.Size : tabSeparatorLeft.Size;
            imgPhoto.Left = 
                (((590 / tabs.Length) * separatorNr) < (tabSeparatorLeft.Width + tabSelected.Width) 
                    ? ((590 / tabs.Length) * separatorNr)
                    : (tabSeparatorLeft.Width + tabSelected.Width) * separatorNr) + 
                    ((590 / tabs.Length - tabs.Length * tabSeparatorLeft.Width) < tabSelected.Width 
                        ? (590 / tabs.Length - tabs.Length * tabSeparatorLeft.Width) 
                        : tabSelected.Width);
            imgPhoto.Top = 0;
            imgPhoto.SizeMode = PictureBoxSizeMode.StretchImage;
            imgPhoto.Image = separatorNr == tabSeparators.Length - 1 
                ? tabEndRight 
                : (selectedTab > separatorNr 
                    ? tabSeparatorLeft 
                    : tabSeparatorRight);

            return imgPhoto;
        }

        #endregion

        #region Delete Functions

        public void DeleteTab(string name)
        {
            bool deleted = false;

            for (int i = 0; i < tabs.Length; i++)
            {
                if (!deleted)
                {
                    deleted = tabs[i].Text == name;
                }
                else
                {
                    tabs[i - 1] = tabs[i];
                }
            }

            Array.Resize<TabButton>(ref tabs, tabs.Length - 1);
        }

        #endregion

        #region Update Functions

        public TabButton[] InitializeTabs(int p_selectedTab)
        {
            for (int i = 0; i < tabs.Length; i++)
            {
                tabs[i] = NewTab(tabs[i].Text, i == p_selectedTab ? SelectPosition.selected : (i < p_selectedTab ? SelectPosition.left : SelectPosition.right), i);
            }

            tabSeparators = new PictureBox[tabs.Length];

            for (int i = 0; i < tabSeparators.Length; i++)
            {
                tabSeparators[i] = NewSeparator(i, p_selectedTab);
            }

            TabButtonContainer.Controls.Clear();
            TabButtonContainer.Controls.AddRange(tabs);
            //TabButtonContainer.Controls.AddRange(tabSeparators);

            selectedPlugin = Global.Plugins.AvailablePlugins.Find(tabs[p_selectedTab].Text);
            if (selectedPlugin != null)
            {
                // Clear visuals: doesn't close the instance of the plugin
                TabContentContainer.Controls.Clear();

                // Set the dockstyle of the plugin to fill, to fill up the space provided
                selectedPlugin.Instance.MainInterface.Dock = DockStyle.Fill;

                // Finally, add the usercontrol to the panel
                TabContentContainer.Controls.Add(selectedPlugin.Instance.MainInterface);

            }

            selectedTabNo = p_selectedTab;

            return tabs;
        }

        public TabButton[] UpdateTabs(int p_selectedTab)
        {
            if (selectedTabNo == p_selectedTab) return tabs;
            else if (selectedTabNo == -1) return InitializeTabs(p_selectedTab);

            tabs[p_selectedTab] = NewTab(tabs[p_selectedTab].Text, SelectPosition.selected, p_selectedTab);
            tabs[selectedTabNo] = NewTab(tabs[selectedTabNo].Text, selectedTabNo < p_selectedTab ? SelectPosition.left : SelectPosition.right, selectedTabNo);

            tabSeparators = new PictureBox[tabs.Length];

            for (int i = 0; i < tabSeparators.Length; i++)
            {
                tabSeparators[i] = NewSeparator(i, p_selectedTab);
            }

            //*/
            TabButtonContainer.Controls.Clear();
            TabButtonContainer.Controls.AddRange(tabs);
            //TabButtonContainer.Controls.AddRange(tabSeparators);
            //*/

            selectedPlugin = Global.Plugins.AvailablePlugins.Find(tabs[p_selectedTab].Text);
            if (selectedPlugin != null)
            {
                // Clear visuals: doesn't close the instance of the plugin
                TabContentContainer.Controls.Clear();

                // Set the dockstyle of the plugin to fill, to fill up the space provided
                selectedPlugin.Instance.MainInterface.Dock = DockStyle.Fill;

                // Finally, add the usercontrol to the panel
                TabContentContainer.Controls.Add(selectedPlugin.Instance.MainInterface);

            }

            selectedTabNo = p_selectedTab;

            return tabs;
        }

        #endregion
    }
}
